package com.wangzhen.codebase.transfermoney.lock1;

/**
 * lock0版本的改进，改进点：不再使用synchronized(this) { synchronized(target){} },这种方式可能会造成死锁
 * lock0的方式是先拿到第一把锁，然后再去拿第二把锁；这个版本的一个改进点是同时去获取第一和第二把锁，通过这种方式避免死锁
 *
 * 向生活要答案，远古社会必须要拿到张三、李四两个人的账本才能进行转账：
 * 1、都能拿到------程序正常执行
 * 2、拿到张三账本---等待
 * 3、拿到李四账本---等待
 *
 * a)新建了一个Allocater类，专门用来获取账本（同时申请两个锁资源），释放账本
 * b)Account在转账的时候先使用Allocator来拿账本，拿到再转账，拿不到就等着
 */
public class Account {

    private static final Allocater allocater = new Allocater();

    private Integer balance;

    private Account(Integer balance) {
        this.balance = balance;
    }

    public void transfer(Account target, Integer account) {
        // 没有申请到锁就一直等着
        while (!allocater.apply(this, target))
        try {
            if (this.balance >= account) {
                this.balance -= account;
                target.balance += account;
            } else {
                System.out.println("余额不足！！！");
            }
        } finally {
            // 释放锁
            allocater.free(this, target);
        }
    }
}
